﻿// Inner Fire 游戏引擎库
// Animation - 动画
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：应用层(4)
// 用于保存项目的动画
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-03-12

#pragma once

#include <game/animation/animation_clip.h>
#include <game/animation/armature.h>
#include <game/resource/resource.h>
#include <xml_reader.h>
#include <static_string.h>
#include <ref_info.h>


namespace ifire::game {
class Avatar;


class Animation : public Resource {
public:
  Animation(Assets* manager, const ikit::XmlNode& node);
  Animation(const Animation& lhs) = delete;
  Animation& operator=(const Animation& lhs) = delete;
  ~Animation() = default;

  friend class AnimationClip;

  // 载入此项目
  void Load();
  // 使项目准备好，意思是如果没有载入，则载入
  void Ready();

  // 设置这个项目的引用
  void Setup() override;

  // 获得一个Clip
  AnimationClip* FindClip(ikit::sstr name) const;
  // 获得第一个Clip
  AnimationClip* First() const;

  //std::unique_ptr<Armature> armature_;
  eastl::vector<AnimationClipPtr> clips;

  // 获得项目的Avatar
  const Avatar* GetAvatar() const;

  // ------
  // 属性访问
  // ------
  inline bool IsRootMotion() const { return is_root_motion_; }
  inline bool IsHumanoid() const { return is_humanoid_; }
  inline float GetScaleFactor() const { return scale_factor_; }
  inline float IsScale() const { return scale_factor_ != 1.0f; }
  inline float IsFlipRotation() const { return is_filp_rotation; }
  inline FMat GetFlipRotation() const { return flip_rotation; }
  inline IAxis GetRootMotionAxis() const { return root_motion_axis_; }

private:
  // 查找MasterClip
  AnimationClip* FindMasterClip(ikit::sstr name) const;


  // 动画的载入路径
  std::string path_;
  // 标记这个动画是不是需要进行左手坐标系的转化（即从右手坐标系转化到左手（DX）的坐标系）
  bool convert_left_hand_;
  // 此Animation是否是RootMotion，如果下面的CLIP不自行定义，则继承此属性
  bool is_root_motion_;
  // RootMotion所对应的轴，因为有些动画是会被翻转，导致并不是Z轴是管前进，所以需要指定
  IAxis root_motion_axis_;
  // 标记此动画是否是Humanoid动画（其实这个控制放在这里不合适，但我也不知道放在哪儿合适，只好这样了）
  bool is_humanoid_;
  // 是否需要变换单位。每单位从1cm变换为引擎的1m。
  bool convert_units_;
  // 对动画进行缩放的项目。如果设置，将替代convert_units_中的0.01。默认为1.00，不进行缩放。
  float scale_factor_;
  // 有些动画天生制作出来，朝向就有问题，此时就应该将其翻转。读取的项目是一个欧拉角（角度）。读入后转为四元数。
  IMat flip_rotation;
  // 标记是否拥有flip，不用每次都进行浮点对比运算
  bool is_filp_rotation;
  // 此动画使用的Avatar
  ikit::rinfo<Avatar> avatar_;
};

using AnimationPtr = std::unique_ptr<Animation>;

} // namespace ifire::game